package com.data.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.data.entity.Tenant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import javax.sql.DataSource;
import java.util.Map;

/**
 * 动态切换数据源实现类
 * @author ytj
 * @date 2024/4/19
 */
@Slf4j
public class DynamicDataSource extends AbstractRoutingDataSource {

    private Map<Object,Object> dynamicTargetDataSource;

    public DynamicDataSource(DataSource defaultTargetDataSource,Map<Object,Object> targetDataSources){
        this.setDefaultTargetDataSource(defaultTargetDataSource);
        this.setTargetDataSources(targetDataSources);
        this.dynamicTargetDataSource=targetDataSources;
        super.afterPropertiesSet();
    }

    public DynamicDataSource(){

    }

    /**
     * 如果希望所有数据源在启动时就加载好，则需要定制改方法（通过设置key来切换数据源）
     * 实现数据源切换要扩展的方法，该方法的返回值就是项目中所用到的dataSource的key值
     *拿到该key后就可以在dynamicTargetDataSource中取出对应的dataSource,如果key找不到对应的dataSource就使用默认的数据源
     * */
    @Override
    protected Object determineCurrentLookupKey() {
        String dataSource = DynamicDataSourceContextHolder.getDataSource();
        if(StringUtils.isNotBlank(dataSource)){
            if(this.dynamicTargetDataSource.containsKey(dataSource)){
                log.info("当前数据源为:{}",dataSource);
            }else{
                log.info("不存在的数据源:{}",dataSource);
            }
        }else{
            log.info("当前数据源为默认数据源");
        }
        return dataSource;
    }

    /**
     * 设置数据源
     * */
    @Override
    public void setTargetDataSources(Map<Object, Object> targetDataSources) {
        super.setTargetDataSources(targetDataSources);
        this.dynamicTargetDataSource=targetDataSources;
        //将数据源key放到数据源key的map中用于校验数据源切换时key是否存在
        DynamicDataSourceContextHolder.addDataSourceKeys(targetDataSources.keySet());
    }

    /**
     * 设置默认数据源
     * */
    @Override
    public void setDefaultTargetDataSource(Object defaultTargetDataSource) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
    }

    /**
     * 如果不希望数据源在启动配置时就加载好，可以定制这个方法，从任何你希望的地方读取并返回数据
     *比如从数据库，文件，外接口等读取数据源，最终返回一个DataSource接口就可以
     * */
    @Override
    protected DataSource determineTargetDataSource() {
        return super.determineTargetDataSource();
    }

    /**
     * 添加租户数据源
     * @param tenant
     * */
    public void setDataSoure(Tenant tenant){
        try {
            DruidDataSource dataSource=new DruidDataSource();
            dataSource.setDriverClassName(tenant.getDataSourceDriver());
            dataSource.setUrl(tenant.getDataSourceUrl());
            dataSource.setUsername(tenant.getDataSourceUserName());
            dataSource.setPassword(tenant.getDataSourcePassword());
            this.dynamicTargetDataSource.put(tenant.getCode(),dataSource);
            setTargetDataSources(this.dynamicTargetDataSource);
            super.afterPropertiesSet();
            log.info("租户数据源初始化成功---->"+ tenant.getCode());
        } catch (Exception e) {
            log.error("数据源链接出错:{}",e.getMessage(),e);
        }
    }
}
